package com.macro.mall.service.impl;

import com.macro.mall.common.exception.BusinessException;
import com.macro.mall.config.properties.RedisKeyPrefixConfig;
import com.macro.mall.domain.Register;
import com.macro.mall.domain.UmsMember;
import com.macro.mall.domain.UmsMemberExample;
import com.macro.mall.mapper.UmsMemberMapper;
import com.macro.mall.service.MemberService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;
import java.util.List;
import java.util.Random;
import java.util.concurrent.TimeUnit;

/**
 * {@link MemberService} 实现类
 */
@Slf4j
@EnableConfigurationProperties(value = RedisKeyPrefixConfig.class)
@Service
public class MemberServiceImpl implements MemberService {

    @Autowired
    private UmsMemberMapper umsMemberMapper;

    @Autowired
    private RedisTemplate redisTemplate;

    @Autowired
    private RedisKeyPrefixConfig redisKeyPrefixConfig;

    @Autowired
    private PasswordEncoder passwordEncoder;

    /**
     * 获取动态校验码
     *
     * @param telPhone
     * @return
     */
    @Override
    public String getOtpCode(String telPhone) throws BusinessException {
        //1、查询当前用户有么有注册
        UmsMemberExample example = new UmsMemberExample();
        example.createCriteria().andPhoneEqualTo(telPhone);
        List<UmsMember> results = umsMemberMapper.selectByExample(example);
        if (!CollectionUtils.isEmpty(results)) {
            log.error("phone {} 已经注册!不能重复注册 ", telPhone);
            throw new BusinessException("用户已经注册!不能重复注册");
        }

        //2、校验60s后有没有再次发送
        String redisKey = redisKeyPrefixConfig.getPrefix().getOtpCode() + telPhone;
        log.info("redis key {}", redisKey);
        if (redisTemplate.hasKey(redisKey)) {
            log.error("redis key {} try again in 60s", redisKey);
            throw new BusinessException("请60s后再试!");
        }
        //3、生产随机校验码
        Random random = new Random();
        StringBuilder stb = new StringBuilder();
        for (int j = 0; j < 6; j++) {
            stb.append(random.nextInt(10));
        }
        log.info("otpcode {}", stb.toString());
        redisTemplate.opsForValue().set(redisKey,
                stb.toString(),
                redisKeyPrefixConfig.getExpire().getOtpCode(),
                TimeUnit.SECONDS);
        return stb.toString();
    }

    @Transactional(rollbackFor = {Exception.class})
    @Override
    public int regite(Register register) throws BusinessException {
        String redisKey = redisKeyPrefixConfig.getPrefix().getOtpCode() + register.getPhone();
        log.info("redis key {}", redisKey);
        String otpCode = (String) redisTemplate.opsForValue().get(redisKey);
        if (StringUtils.isEmpty(otpCode) || !otpCode.equals(register.getOtpCode())) {
            log.error("redis key {}: 动态校验码不正确", redisKey);
            throw new BusinessException("动态校验码不正确!");
        }
        UmsMember umsMember = new UmsMember();
        umsMember.setStatus(1);
        umsMember.setMemberLevelId(4L);
        BeanUtils.copyProperties(register, umsMember);
        umsMember.setPassword(passwordEncoder.encode(register.getPassword()));
        log.info("username: {}, password: {}", register.getUsername(), register.getPassword());
        return umsMemberMapper.insertSelective(umsMember);
    }

    @Override
    public UmsMember login(String username, String password) throws BusinessException {
        UmsMemberExample memberExample = new UmsMemberExample();
        memberExample.createCriteria().andUsernameEqualTo(username).andStatusEqualTo(1);
        List<UmsMember> result = umsMemberMapper.selectByExample(memberExample);
        if (CollectionUtils.isEmpty(result)) {
            log.error("用户名：{}，密码：{} 不正确", username, password);
            throw new BusinessException("用户名或密码不正确!");
        }
        if (result.size() > 1) {
            log.error("用户名：{} 被注册过多次,请联系客服!", username);
            throw new BusinessException("用户名被注册过多次,请联系客服!");
        }
        UmsMember member = result.get(0);
        if (!passwordEncoder.matches(password, member.getPassword())) {
            log.error("用户名：{}，密码：{} 不正确", username, password);
            throw new BusinessException("用户名或密码不正确!");
        }
        return member;
    }

}
